#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "kapi.h"
#include "diag.h"
#include "wbio.h"

#include "nvtfat.h"
#include "nuc900_reg.h"


#define THREAD_CNT		10
#define TEST_LOOP		2

#define STACK_SIZE		(32*1024)

static cyg_handle_t  	hTest, _hThreadArray[THREAD_CNT];
static cyg_thread 		ThreadTest, _ThreadArray[THREAD_CNT];
static UINT8            _Stack[STACK_SIZE], _StackArray[THREAD_CNT][STACK_SIZE];

extern VOID  fsGetErrorDescription(INT nErrCode, CHAR *szDescription, INT bIsPrint);
extern INT   fsBIG5toUnicode(VOID *bstr, VOID *ustr);


/* imported from NVTFAT_DISK.C */
extern PDISK_T		*_fs_ptPDiskList;


static volatile BOOL _bIsCardInserted = FALSE;


static INT  Action_Compare(CHAR *suFileName1, CHAR *szAsciiName1, 
							CHAR *suFileName2, CHAR *szAsciiName2)
{
	INT		hFile1, hFile2;
	INT		nLen1, nLen2, nCount, nStatus1, nStatus2;
	UINT8	buffer1[8192], buffer2[8192];
	
	hFile1 = fsOpenFile(suFileName1, szAsciiName1, O_RDONLY);
	if (hFile1 < 0)
		return hFile1;
	
	hFile2 = fsOpenFile(suFileName2, szAsciiName2, O_RDONLY);
	if (hFile2 < 0)
		return hFile2;
	nCount = 0;
	while (1)
	{
		nStatus1 = fsReadFile(hFile1, buffer1, 8192, &nLen1);
		nStatus2 = fsReadFile(hFile2, buffer2, 8192, &nLen2);
		
		if ((nStatus1 == ERR_FILE_EOF) && (nStatus2 == ERR_FILE_EOF))
		{
			fsCloseFile(hFile1);
			fsCloseFile(hFile2);
			return 0;
		}
		
		if (nLen1 != nLen2)
			break;
			
		if (memcmp(buffer1, buffer2, 8192))
			break;
		
		nCount++;
		//if ((nCount % 1024) == 0)
		//	diag_printf("%d KB    \r", nCount);
	}
	
	diag_printf("\nFile Compare failed at offset %x\n", nCount * 1024);
	
	fsCloseFile(hFile1);
	fsCloseFile(hFile2);
	return -1;
}

static volatile int  task_idx = 0;

void copy_compare_test(cyg_addrword_t data)
{
	INT     tidx, i, nStatus;
	CHAR	suFileSrc[24] = { 'C',0,':',0,'\\',0,'1',0,0,0 };
	CHAR	suFileDst[24] = { 'C',0,':',0,'\\',0,'a',0,0,0 };

	tidx = task_idx++;

	suFileSrc[6] = '0' + tidx;
	suFileDst[6] = 'a' + tidx;

	diag_printf("Task %d running...\n", tidx);
	for (i = 0; i < TEST_LOOP; i++)
	{
		do 
		{
			nStatus = fsDeleteFile(suFileDst, NULL);
		}	while (nStatus == ERR_OPEN_WRITE_OPENED);
		
		diag_printf("%d Copy file %s (LOOP:%d)\n", tidx, fsDebugUniStr(suFileSrc), i);
retry:		
		nStatus = fsCopyFile(suFileSrc, NULL, suFileDst, NULL);
		if (nStatus == ERR_OPEN_WRITE_OPENED)
		{
			//diag_printf("Opened, retry.\n");
			goto retry;
		}
		if (nStatus < 0)
		{
			diag_printf("%d Failed, status = %x\n", tidx, nStatus);
			break;
		}

		diag_printf("%d Compare file (LOOP:%d)\n", tidx, i);
		nStatus = Action_Compare(suFileSrc, NULL, suFileDst, NULL);
		if (nStatus < 0)
		{
			diag_printf("%d Failed, status = %x\n", tidx, nStatus);
			break;
		}
		diag_printf("%d Compare file (LOOP:%d)\n", tidx, i);
	}	
	diag_printf("%d Test OK.\n", tidx);
}




void test_main(cyg_addrword_t data)
{
	INT  i;
	
	for (i = 0; i < THREAD_CNT; i++)
	{
 		cyg_thread_create(12, copy_compare_test, i, NULL, 
 							_StackArray[i], STACK_SIZE, &_hThreadArray[i], &_ThreadArray[i]);
		cyg_thread_resume(_hThreadArray[i]);
	}
}



int  main(char *argc[],char *argv[])
{
	WB_PLL_T 		sysClock;

	/* CACHE_ON	*/
	sysInvalidCache();
	sysEnableCache(CACHE_WRITE_BACK);

	sysClock.pll0 = PLL_166MHZ;				//PLL0 output clock
	sysClock.pll1 = PLL_120MHZ;				//PLL1 output clock
	sysClock.cpu_src = CPU_FROM_PLL0;		//Select CPU clock source
	sysClock.ahb_clk = AHB_CPUCLK_1_2;		//Select AHB clock divider
	sysClock.apb_clk = APB_AHB_1_2;			//Select APB clock divider
	sysSetPLLConfig(&sysClock);				//Call system function call

	fsInitFileSystem();

	InitUsbSystem();       
	UMAS_InitUmasDriver();

	//fsScanDisk('C');
		
 	cyg_thread_create(10, test_main, 0, NULL, _Stack, STACK_SIZE, &hTest, &ThreadTest);
	cyg_thread_resume(hTest);
	
	return 0;
}


